﻿using DevExpress.Data.Filtering;
using Newtonsoft.Json;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Services;
using Volo.Abp.Security.Encryption;
using Volo.Abp.Uow;
using YAKEJI.Abp.ChineseChar;
using YAKEJI.Abp.Domain.Repositories;
using YAKEJI.Xaf.DataDictionaries;
using YAPACS.BusinessObjects.Exams;
using YAPACS.BusinessObjects.Managements.Appointments;
using YAPACS.BusinessObjects.Managements.Devices;
using YAPACS.BusinessObjects.Managements.Exams;
using YAPACS.BusinessObjects.Managements.ExpertGroups;
using YAPACS.BusinessObjects.Managements.StoreServices;
using YAPACS.Organizations;
using YAPACS.RisServer.Abstractions;
using YAPACS.RisServer.Services.Dtos;
using YAPACS.RisServer.Workflows.Register;
using YAPACS.Workflows;

namespace YAPACS.RisServer.Services;

public class RegisterService(IGetAdvancedSearchView getAdvancedSearchView, IPending pending, ICancelPending cancelPending, IRefund refund, ISetArrived setArrived,
    ISetTop setTop, ISetBottom setBottom, ISetPrevious setPrevious, ISetNext setNext, IRepository<Exam, Guid> examRepository,
    IUnitOfWorkManager unitOfWorkManager, IGetEmergencyRegistView getEmergencyRegistView, IExamQueueService examQueueService,
    IRepository<Department, Guid> departmentRepository, ICurrentUserOrganization currentUserOrganization, IExamPermissionService examPermissionService,
    IExamEventService examEventService, IAccountVerifyService accountVerifyService,
    ICandidate candidate, IRepository<DeviceType, Guid> deviceTypeRepository,
    IRepository<ExamBodyParty, Guid> examBodyPartyRepository,
    IRepository<ExamMethod, Guid> examMethodRepository, IRepository<ExamItem, Guid> examItemRepository,
    IRepository<Patient, Guid> patientRepository, IRepository<DataDictItem, Guid> dataDicItemRepository,
    IRepository<PatientFrom, Guid> patientFromRepository, IRepository<PatientFeature, Guid> patientFeatureRepository,
    IRepository<PatientMatter, Guid> patientMatterRepository, IRepository<ApplyDoctor, Guid> applyDoctorRepository,
    IRepository<ApplyDepartment, Guid> applyDepartmentRepository, IRepository<Device, Guid> deviceRepository,
    IRepository<AppointmentPlan, Guid> appointmentPlanRepository, IRepository<ExamCategory, Guid> examCategoryRepository,
    ICreateExam createExam, ISaveExam saveExam, IGetHeaders getHeaders, IGetRowStyle getRowStyle, ISubmitExam submitExam,
    IAdvancedSearchExpression advancedSearchExpression, IGetExam getExam, IGetExamView getExamView, IGetDefaultFilter getDefaultFilter,
    IChineseCharProvider chineseCharProvider, IExamNumberService examNumberService, IExamListService examListService,
    IRepository<ApplicationUser, Guid> userRepository, IDeviceService deviceService, IBeforeSubmit beforeSubmit, IRepository<ExpertGroup, Guid> expertGroupRepository,
    IExportService exportService, IStringEncryptionService stringEncryptionService, IDeleted deleted)
    : DomainService, IRegisterService, ITransientDependency
{
    private readonly IUnitOfWorkManager _unitOfWorkManager = unitOfWorkManager;
    private readonly IRepository<Exam, Guid> _examRepository = examRepository;
    private readonly IGetAdvancedSearchView _getAdvancedSearchView = getAdvancedSearchView;
    private readonly IPending _pending = pending;
    private readonly ICancelPending _cancelPending = cancelPending;
    private readonly IRefund _refund = refund;
    private readonly ISetArrived _setArrived = setArrived;
    private readonly ISetTop _setTop = setTop;
    private readonly ISetBottom _setBottom = setBottom;
    private readonly ISetPrevious _setPrevious = setPrevious;
    private readonly ISetNext _setNext = setNext;
    private readonly IGetEmergencyRegistView _getEmergencyRegistView = getEmergencyRegistView;
    private readonly IExamQueueService _examQueueService = examQueueService;
    private readonly IRepository<Department, Guid> _departmentRepository = departmentRepository;
    private readonly ICurrentUserOrganization _currentUserOrganization = currentUserOrganization;
    private readonly IExamPermissionService _examPermissionService = examPermissionService;
    private readonly IExamEventService _examEventService = examEventService;
    private readonly IAccountVerifyService _accountVerifyService = accountVerifyService;
    private readonly ICandidate _candidate = candidate;
    private readonly IRepository<DeviceType, Guid> _deviceTypeRepository = deviceTypeRepository;
    private readonly IRepository<ExamBodyParty, Guid> _examBodyPartyRepository = examBodyPartyRepository;
    private readonly IRepository<ExamMethod, Guid> _examMethodRepository = examMethodRepository;
    private readonly IRepository<ExamItem, Guid> _examItemRepository = examItemRepository;
    private readonly IRepository<Patient, Guid> _patientRepository = patientRepository;
    private readonly IRepository<DataDictItem, Guid> _dataDicItemRepository = dataDicItemRepository;
    private readonly IRepository<PatientFrom, Guid> _patientFromRepository = patientFromRepository;
    private readonly IRepository<PatientFeature, Guid> _patientFeatureRepository = patientFeatureRepository;
    private readonly IRepository<PatientMatter, Guid> _patientMatterRepository = patientMatterRepository;
    private readonly IRepository<ApplyDoctor, Guid> _applyDoctorRepository = applyDoctorRepository;
    private readonly IRepository<ApplyDepartment, Guid> _applyDepartmentRepository = applyDepartmentRepository;
    private readonly IRepository<Device, Guid> _deviceRepository = deviceRepository;
    private readonly IRepository<AppointmentPlan, Guid> _appointmentPlanRepository = appointmentPlanRepository;
    private readonly IRepository<ExamCategory, Guid> _examCategoryRepository = examCategoryRepository;
    private readonly ICreateExam _createExam = createExam;
    private readonly ISaveExam _saveExam = saveExam;
    private readonly IGetHeaders _getHeaders = getHeaders;
    private readonly IGetRowStyle _getRowStyle = getRowStyle;
    private readonly ISubmitExam _submitExam = submitExam;
    private readonly IAdvancedSearchExpression _advancedSearchExpression = advancedSearchExpression;
    private readonly IGetExam _getExam = getExam;
    private readonly IGetExamView _getExamView = getExamView;
    private readonly IGetDefaultFilter _getDefaultFilter = getDefaultFilter;
    private readonly IChineseCharProvider _chineseCharProvider = chineseCharProvider;
    private readonly IExamNumberService _examNumberService = examNumberService;
    private readonly IExamListService _examListService = examListService;
    private readonly IRepository<ApplicationUser, Guid> _userRepository = userRepository;
    private readonly IDeviceService _deviceService = deviceService;
    private readonly IBeforeSubmit _beforeSubmit = beforeSubmit;
    private readonly IRepository<ExpertGroup, Guid> _expertGroupRepository = expertGroupRepository;
    private readonly IExportService _exportService = exportService;
    private readonly IStringEncryptionService _stringEncryptionService = stringEncryptionService;
    private readonly IDeleted _deleted = deleted;

    private async Task UpdatePatientAsync(Patient patient, PatientDto patientDto)
    {
        if (!string.IsNullOrWhiteSpace(patientDto.PatientId))
        {
            patient.PatientId = patientDto.PatientId;
        }

        patient.Name = patientDto.Name;
        patient.NamePinYin = patientDto.NamePinYin;

        if ((!string.IsNullOrWhiteSpace(patient.Name)) && string.IsNullOrWhiteSpace(patient.NamePinYin))
        {
            patient.NamePinYin = await GetPinYinAsync(patient.Name);
        }

        patient.Sex = (PatientSex?)patientDto.Sex;
        patient.BirthDate = patientDto.BirthDate != null ? Convert.ToDateTime(patientDto.BirthDate) : null;


        if (patientDto.IdCardType == null)
        {
            patient.IdCardType = null;
        }
        else
        {
            patient.IdCardType = await _dataDicItemRepository.FirstOrDefaultAsync(e => e.Id == patientDto.IdCardType.Value);
        }

        patient.IdCardNumber = patientDto.IdCardNumber;

        if (patientDto.MedicalInsuranceType == null)
        {
            patient.MedicalInsuranceType = null;
        }
        else
        {
            patient.MedicalInsuranceType = await _dataDicItemRepository.FirstOrDefaultAsync(e => e.Id == patientDto.MedicalInsuranceType.Value);
        }

        patient.MedicalInsuranceNumber = patientDto.MedicalInsuranceNumber;
        patient.PhoneNumber = patientDto.PhoneNumber;
        patient.PhoneNumber2 = patientDto.PhoneNumber2;
        patient.Address = patientDto.Address;

        if (patientDto.EthnicGroup == null)
        {
            patient.EthnicGroup = null;
        }
        else
        {
            patient.EthnicGroup = await _dataDicItemRepository.FirstOrDefaultAsync(e => e.Id == patientDto.EthnicGroup.Value);
        }
    }

    private async Task UpdateExamAsync(Exam exam, ExamDto examDto)
    {
        //创建患者
        exam.Patient ??= await _patientRepository.NewEntityAsync();
        if (examDto.Patient != null)
        {
            if (exam.Patient.Oid != examDto.Patient.Oid)
            {
                //选择了已经存在的患者
                exam.Patient = await _patientRepository.GetAsync(examDto.Patient.Oid);
            }
            await UpdatePatientAsync(exam.Patient, examDto.Patient);
        }

        exam.AccessionNumber = examDto.AccessionNumber;
        exam.AgeValue = examDto.AgeValue;
        exam.AgeUnit = (AgeUnit?)examDto.AgeUnit;
        exam.Height = examDto.Height;
        exam.Weight = examDto.Weight;

        if (examDto.PatientFrom == null)
        {
            exam.PatientFrom = null;
        }
        else
        {
            exam.PatientFrom = await _patientFromRepository.FirstOrDefaultAsync(e => e.Id == examDto.PatientFrom.Value);
        }

        if (examDto.PatientType == null)
        {
            exam.PatientType = null;
        }
        else
        {
            exam.PatientType = await _dataDicItemRepository.FirstOrDefaultAsync(e => e.Id == examDto.PatientType.Value);
        }

        exam.PhysicalExamNumber = examDto.PhysicalExamNumber;
        exam.OutPatientNumber = examDto.OutPatientNumber;
        exam.InPatientNumber = examDto.InPatientNumber;
        exam.InPatientArea = examDto.InPatientArea;
        exam.WardNumber = examDto.WardNumber;
        exam.BedNumber = examDto.BedNumber;
        exam.ApplyTime = exam.Id != Guid.Empty ? exam.ApplyTime : Clock.Now;

        if (examDto.ApplyDepartment == null)
        {
            exam.ApplyDepartment = null;
        }
        else
        {
            exam.ApplyDepartment = await _applyDepartmentRepository.FirstOrDefaultAsync(e => e.Id == examDto.ApplyDepartment.Value);
        }

        if (examDto.ApplyDoctor == null)
        {
            exam.ApplyDoctor = null;
        }
        else
        {
            exam.ApplyDoctor = await _applyDoctorRepository.FirstOrDefaultAsync(e => e.Id == examDto.ApplyDoctor.Value);
        }

        exam.ClinicalDiagnosis = examDto.ClinicalDiagnosis;

        if (examDto.Profession == null)
        {
            exam.Profession = null;
        }
        else
        {
            exam.Profession = await _dataDicItemRepository.FirstOrDefaultAsync(e => e.Id == examDto.Profession.Value);
        }

        if (examDto.MaritalStatus == null)
        {
            exam.MaritalStatus = null;
        }
        else
        {
            exam.MaritalStatus = await _dataDicItemRepository.FirstOrDefaultAsync(e => e.Id == examDto.MaritalStatus.Value);
        }

        exam.MenstrualHistory = examDto.MenstrualHistory;
        exam.LastMenstruationDate = examDto.LastMenstruationDate;
        exam.GestationalWeek = examDto.GestationalWeek;
        exam.ChildbirthDate = examDto.ChildbirthDate;
        exam.IsPregnancy = examDto.IsPregnancy;
        exam.Remark = examDto.Remark;
        exam.IsEmergency = examDto.IsEmergency;

        if (examDto.ExamCategory == null)
        {
            exam.ExamCategory = null;
        }
        else
        {
            exam.ExamCategory = await _examCategoryRepository.FirstOrDefaultAsync(e => e.Id == examDto.ExamCategory.Value);
        }

        exam.MedicalHistory = examDto.MedicalHistory;
        exam.ChiefComplaint = examDto.ChiefComplaint;
        exam.AllergyHistory = examDto.AllergyHistory;

        if (examDto.ExamDevice == null)
        {
            exam.ExamDevice = null;
        }
        else
        {
            exam.ExamDevice = await _deviceRepository.FirstOrDefaultAsync(e => e.Id == examDto.ExamDevice.Value);
        }

        if (examDto.DeviceType == null)
        {
            exam.DeviceType = null;
        }
        else
        {
            exam.DeviceType = await _deviceTypeRepository.FirstOrDefaultAsync(e => e.Id == examDto.DeviceType.Value);
        }
    }

    private async Task UpdateExamMethodsAsync(Exam exam, ExamDto examDto)
    {
        exam.ExamMethods.RemoveAll(e => true);
        if (examDto.ExamMethods != null && examDto.ExamMethods.Count > 0)
        {
            var examMethodIds = examDto.ExamMethods.Select(e => e.Oid);
            var examMethods = await _examMethodRepository.GetListAsync(e => examMethodIds.Contains(e.Id));
            exam.ExamMethods.AddRange(examMethods);
            exam.ExamMethodsText = string.Join(",", exam.ExamMethods.Select(m => m.GetShortName()).ToArray());
        }
    }

    private async Task UpdateExamBodyPartiesAsync(Exam exam, ExamDto examDto)
    {
        exam.ExamBodyParties.RemoveAll(e => true);
        if (examDto.ExamBodyParties != null && examDto.ExamBodyParties.Count > 0)
        {
            var oids = examDto.ExamBodyParties.Select(e => e.Oid);
            var examBodyParties = await _examBodyPartyRepository.GetListAsync(e => oids.Contains(e.Id));
            exam.ExamBodyParties.AddRange(examBodyParties);
            exam.ExamBodyPartiesText = string.Join(",", exam.ExamBodyParties.Select(m => m.GetShortName()).ToArray());
        }
    }

    private async Task UpdatePatientFeaturesAsync(Exam exam, ExamDto examDto)
    {
        exam.PatientFeatures.RemoveAll(e => true);
        if (examDto.PatientFeatures != null && examDto.PatientFeatures.Count > 0)
        {
            var oids = examDto.PatientFeatures.Select(e => e.Oid);
            var patientFeatures = await _patientFeatureRepository.GetListAsync(e => oids.Contains(e.Id));
            exam.PatientFeatures.AddRange(patientFeatures);
            exam.PatientFeaturesText = string.Join(",", exam.PatientFeatures.Select(m => m.GetShortName()).ToArray());
        }
    }

    private async Task UpdateExamItemsAsync(Exam exam, ExamDto examDto)
    {
        exam.ExamItems.RemoveAll(e => true);
        if (examDto.ExamItems != null && examDto.ExamItems.Count > 0)
        {
            var oids = examDto.ExamItems.Select(e => e.Oid);
            var examItems = await _examItemRepository.GetListAsync(e => oids.Contains(e.Id));

            exam.ExamItems.AddRange(examItems);
            exam.ExamItemsText = string.Join(",", exam.ExamItems.Select(m => m.GetShortName()).ToArray());
            exam.UpdateShared();
        }
    }

    private async Task<WorkflowOutput> InvokeSaveWorkflowAsync(Exam exam)
    {
        var workflowOutput = await _saveExam.InvokeAsync(new WorkflowInput { { "Exam", exam } });
        if (!workflowOutput.Success)
        {
            throw new Exception(workflowOutput.Error);
        }

        return workflowOutput;
    }

    private async Task UpdateExpertGroup(Exam exam, ExamDto examDto)
    {
        if (!string.IsNullOrEmpty(examDto.ExpertGroup))
        {
            exam.ExpertGroup = await _expertGroupRepository.GetAsync(Guid.Parse(examDto.ExpertGroup));
        }
        else
        {
            exam.ExpertGroup = null;
        }
    }

    public async Task<WorkflowOutput> CreateAsync(Guid deviceTypeId)
    {
        using var uow = _unitOfWorkManager.Begin(requiresNew: true);
        try
        {
            //创建对象
            var exam = await _examRepository.NewEntityAsync();
            exam.Patient ??= await _patientRepository.NewEntityAsync();
            //设置默认值
            exam.DeviceType = await _deviceTypeRepository.GetAsync(deviceTypeId);
            var department = await _departmentRepository.GetAsync(_currentUserOrganization.DepartmentId.Value);
            exam.Department = department;
            exam.ExamDevice = await _deviceService.GetDeviceIfOnlyOneAsync(deviceTypeId);
            exam.ExamStatus = ExamStatus.Create;
            exam.StoreService = exam.Department.GetStoreService();
            await _examEventService.AddExamEventAsync(exam, "新建检查");
            await _examNumberService.SetNumberAsync(exam);
            //工作流
            var workflowOutput = await _createExam.InvokeAsync(new WorkflowInput() { { "Exam", exam } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            await uow.CompleteAsync();
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await uow.RollbackAsync();
            return new WorkflowOutput()
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GetExamAsync(Guid examId)
    {
        try
        {
            List<string> userPermissions = [];
            var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);
            var permissions = user.GetUserPermissions().Select(e => e.Name).ToList();
            var exam = await _examRepository.GetAsync(examId);
            var department = await _departmentRepository.GetAsync(_currentUserOrganization.DepartmentId.Value);
            if (exam.ExamStatus == ExamStatus.Create && permissions.Contains("登记_保存"))
            {
                userPermissions.Add("登记_保存");
            }
            if (exam.ExamStatus == ExamStatus.Create && permissions.Contains("登记_提交"))
            {
                userPermissions.Add("登记_提交");
            }
            if (exam.ExamStatus > ExamStatus.Create)
            {
                if (!(exam.Studies.Count > 0 || exam.Report != null))
                {
                    userPermissions.Add("登记_撤回");
                }
                else
                {
                    userPermissions.Add("登记_修正");
                }
            }
            //[患者到诊][等候队列]权限
            if (department == exam.Department)
            {
                if (exam.ExamStatus == ExamStatus.Appointment && exam.ExamQueuing == null && exam.ExamAppointment != null)
                {
                    // 在预约检查时间段内
                    if (exam.ExamAppointment.StartTime.Date == Clock.Now.Date)
                    {
                        userPermissions.Add("登记_患者到诊");
                    }
                }
                if (exam.ExamQueuing != null && exam.ExamQueuing.QueuingTime.Date == Clock.Now.Date) // 当天的等候队列
                {
                    userPermissions.Add("登记_等候队列");
                }
            }
            var workflowOutput = await _getExam.InvokeAsync(new WorkflowInput { { "Exam", exam }, { "Permissions", userPermissions } });
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GetExamViewAsync(Guid examId)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            var workflowOutput = await _getExamView.InvokeAsync(new WorkflowInput { { "Exam", exam } });
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> SaveAsync(ExamDto examDto, string editReason)
    {
        using var uow = _unitOfWorkManager.Begin(requiresNew: true);
        try
        {
            var exam = await _examRepository.GetAsync(examDto.Oid);
            await _examPermissionService.ValidateAsync(exam);

            await UpdateExamAsync(exam, examDto);
            await UpdateExamMethodsAsync(exam, examDto);
            await UpdateExamBodyPartiesAsync(exam, examDto);
            await UpdatePatientFeaturesAsync(exam, examDto);
            await UpdateExamItemsAsync(exam, examDto);
            await UpdateExpertGroup(exam, examDto);

            if (!string.IsNullOrWhiteSpace(editReason))
            {
                await _examEventService.AddExamEventAsync(exam, "修正检查", editReason);
            }

            await _examNumberService.SetNumberAsync(exam);

            var workflowOutput = await InvokeSaveWorkflowAsync(exam);

            await uow.CompleteAsync();

            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await uow.RollbackAsync();
            return new WorkflowOutput()
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    private async Task SetAppointmentPlanAsync(Exam exam, ExamDto examDto)
    {
        if (examDto.AppointmentPlan == null)
        {
            exam.AppointmentPlan = null;
            exam.AppointmentTime = DateTime.Today;
        }
        else
        {
            var appointmentPlan = await _appointmentPlanRepository.FirstOrDefaultAsync(e => e.Id == examDto.AppointmentPlan.Value);
            exam.AppointmentPlan = appointmentPlan;
        }
    }

    public async Task<WorkflowOutput> GetExamListByFilterAsync(DataGridRequest request)
    {
        try
        {
            CriteriaOperator criteriaOperator = null;
            var result = await _examListService.GetListByFilterAsync(request, criteriaOperator, _advancedSearchExpression, _getHeaders);
            return result;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput()
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> SubmitAsync(Guid examId)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            await _examPermissionService.ValidateAsync(exam);

            if (exam.ExamStatus != ExamStatus.Create)
            {
                throw new Exception("检查申请已提交，请勿重复提交");
            }
            var workflowOutput = await _beforeSubmit.InvokeAsync(new WorkflowInput { { "Exam", exam } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            //没有预约或者预约时间为当天，检查状态为分诊
            if (exam.AppointmentPlan != null && exam.AppointmentTime.Value.Date != DateTime.Today)
            {
                exam.ExamStatus = ExamStatus.Appointment;
            }
            else
            {
                exam.ExamStatus = ExamStatus.Triage;
                workflowOutput = await _candidate.InvokeAsync(new WorkflowInput { { "Exams", new List<Exam> { exam } } });
                if (!workflowOutput.Success)
                {
                    throw new Exception(workflowOutput.Error);
                }
            }
            exam.ExamQueuing = await _examQueueService.CreateExamQueuingAsync(exam);
            if (exam.ExamQueuing != null && string.IsNullOrWhiteSpace(exam.ExamQueuing.CallNumber))
            {
                await _examNumberService.SetQueueNumberAsync(exam.ExamQueuing);
            }
            await _examNumberService.SetNumberAsync(exam);
            await _examEventService.AddExamEventAsync(exam, "提交检查");
            //提交逻辑
            //提交失败，保存数据，但是不提交
            workflowOutput = await _submitExam.InvokeAsync(new WorkflowInput { { "Exam", exam } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput()
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> DeleteAsync(WorkflowInput input, string nextApi = null)
    {
        try
        {
            var examIds = JsonConvert.DeserializeObject<IList<Guid>>(input.GetValueOrDefault("examIds").ToString() ?? "[]");
            if (examIds.Count == 0)
            {
                return new WorkflowOutput
                {
                    Success = false,
                    Error = "没有找到需要删除的检查"
                };
            }
            var exams = await _examRepository.GetListAsync(e => examIds.Contains(e.Oid));
            var department = await _departmentRepository.GetAsync(_currentUserOrganization.DepartmentId.Value);
            List<string> errMessages = [];
            foreach (var exam in exams)
            {
                if (!await _examPermissionService.IsValidAsync(exam))
                {
                    errMessages.Add($"检查【{exam.AccessionNumber}】不属于本科室");
                }
            }
            if (errMessages.Count > 0)
            {
                throw new Exception(string.Join("<br />", errMessages));
            }
            var userName = input.GetValueOrDefault("userName")?.ToString();
            var password = input.GetValueOrDefault("password")?.ToString();
            if (string.IsNullOrWhiteSpace(userName))
            {
                var workflowOutput = await _accountVerifyService.GetVerifyViewAsync();
                if (!string.IsNullOrWhiteSpace(nextApi))
                {
                    workflowOutput.NextApi = nextApi;
                }
                return workflowOutput;
            }
            else
            {
                var workflowOutput = await _accountVerifyService.VerifyAsync(userName, password, "登记_删除", exams[0]);
                if (workflowOutput.Success)
                {
                    //删除
                    foreach (var exam in exams)
                    {
                        //if (exam.AppointmentPlan != null)
                        //{
                        //    exam.AppointmentPlan.CurrentCount = Math.Max(0, --exam.AppointmentPlan.CurrentCount);
                        //}
                        exam.ReportCandidate = null;
                        exam.AppointmentPlan = null;
                        exam.ExamQueuing?.Delete();
                        exam.ExamQueuing = null;
                        exam.ExamApplyItems.DeleteObjectOnRemove = true;
                        exam.ExamApplyItems.RemoveAll(e => true);
                        await _examEventService.AddExamEventAsync(exam, "删除检查");
                        workflowOutput = await _deleted.InvokeAsync(new WorkflowInput { { "Exam", exam } });
                    }
                    await _examRepository.DeleteManyAsync(exams);
                }
                return workflowOutput;
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    private async Task<string> GetPinYinAsync(string name)
    {
        var result = await _chineseCharProvider.GetPinYinAsync(name);
        return string.Join("", result);
    }

    public async Task<WorkflowOutput> RevokeAsync(WorkflowInput input, string nextApi = null)
    {
        try
        {
            var examId = Guid.Parse(input.GetValueOrDefault("examId")?.ToString());
            var exam = await _examRepository.GetAsync(examId);
            await _examPermissionService.ValidateAsync(exam);
            //撤回条件
            if (exam.ExamStatus >= ExamStatus.Exam)
            {
                throw new Exception("已开始检查，不能撤回");
            }
            if (!input.ContainsKey("reason"))
            {
                var workflowOutput = new WorkflowOutput
                {
                    Success = true,
                    ViewTitle = "撤回登记",
                    View = await Extensions.GetResourceStringAsync("Resources.Register.revoke-view.json"),
                    Data = new { Reason = "" }
                };
                if (!string.IsNullOrWhiteSpace(nextApi))
                {
                    workflowOutput.NextApi = nextApi;
                }
                return workflowOutput;
            }
            else
            {
                exam.ExamStatus = ExamStatus.Create;
                exam.ReportCandidate = null;
                var reason = input.GetValueOrDefault("reason") as string;
                await _examEventService.AddExamEventAsync(exam, "撤回检查", reason);
                //处理逻辑
                return new WorkflowOutput
                {
                    Success = true,
                    Data = exam.Oid
                };
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> ExportAsync(DataGridRequest request)
    {
        try
        {
            CriteriaOperator criteriaOperator = null;
            var file = await _exportService.ExportListToFileAsync(request, criteriaOperator, _advancedSearchExpression, _getHeaders);
            if (File.Exists(file))
            {
                return new WorkflowOutput()
                {
                    Success = true,
                    Data = _stringEncryptionService.Encrypt(Path.GetFileName(file)),
                };
            }
            else
            {
                return new WorkflowOutput()
                {
                    Success = false,
                    Error = "导出列表失败，请稍后重试"
                };
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput()
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GetAdvancedSearchViewAsync()
    {
        try
        {
            var workflowOutput = await _getAdvancedSearchView.InvokeAsync([]);
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> PendingAsync(IList<Guid> examIds)
    {
        try
        {
            var exams = await _examRepository.GetListAsync(e => examIds.Contains(e.Oid));
            foreach (var exam in exams)
            {
                if (!await _examPermissionService.IsValidAsync(exam))
                {
                    throw new Exception($"检查【{exam.AccessionNumber}】不属于本科室");
                }
            }

            var department = await _departmentRepository.GetAsync(_currentUserOrganization.DepartmentId.Value);
            List<string> errorMessages = [];

            foreach (var exam in exams)
            {
                var errorMessage = VerifyQueuing(exam, department);
                if (errorMessage != null)
                {
                    errorMessages.Add(errorMessage);
                }
            }

            if (errorMessages.Count > 0)
            {
                throw new Exception(string.Join("<br>", errorMessages));
            }

            var workflowOutput = await _pending.InvokeAsync(new WorkflowInput { { "Exams", exams } });
            exams = exams
                .Where(e => e.ExamQueuing != null)
                .Where(e => !e.ExamQueuing.IsPending)
                .Where(e => e.ExamQueuing.Status != ExamQueuingStatus.Completed)
                .Where(e => e.Report == null)
                .ToList();

            if (exams.Count != 0)
            {
                foreach (var exam in exams)
                {
                    exam.ExamQueuing.Status = ExamQueuingStatus.Pending;
                    exam.ExamQueuing.IsPending = true;

                    await _examEventService.AddExamEventAsync(exam, "挂起患者");
                }
            }
            else
            {
                return new WorkflowOutput
                {
                    Success = false,
                    Error = "当前检查无法进行挂起操作"
                };
            }

            //修改状态 挂起
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    private string VerifyQueuing(Exam exam, Department department)
    {
        var now = Clock.Now;
        //不是当前科室
        if (exam.Department != department)
        {
            return $"当前检查【{exam.Patient.Name}({exam.AccessionNumber})】不属于本科室";
        }
        if (exam.ExamQueuing == null)
        {
            return $"当前检查【{exam.Patient.Name}({exam.AccessionNumber})】未到诊";
        }
        if (exam.ExamStatus == ExamStatus.Completed)
        {
            return $"当前检查【{exam.Patient.Name}({exam.AccessionNumber})】已完成";
        }
        //时间
        if (exam.ExamAppointment != null && exam.ExamAppointment.StartTime.Date != now.Date)
        {
            if (exam.ExamAppointment.StartTime.Date > now.Date)
            {
                return $"当前检查【{exam.Patient.Name}({exam.AccessionNumber})】未到检查时间";
            }
            else
            {
                return $"当前检查【{exam.Patient.Name}({exam.AccessionNumber})】已过期";
            }
        }
        return null;
    }

    public async Task<WorkflowOutput> CancelPendingAsync(IList<Guid> examIds)
    {
        try
        {
            var exams = await _examRepository.GetListAsync(e => examIds.Contains(e.Oid));
            foreach (var exam in exams)
            {
                if (!await _examPermissionService.IsValidAsync(exam))
                {
                    throw new Exception($"检查【{exam.AccessionNumber}】不属于本科室");
                }
            }

            var department = await _departmentRepository.GetAsync(_currentUserOrganization.DepartmentId.Value);
            List<string> errorMessages = [];

            foreach (var exam in exams)
            {
                var errorMessage = VerifyQueuing(exam, department);
                if (errorMessage != null)
                {
                    errorMessages.Add(errorMessage);
                }
            }

            if (errorMessages.Count > 0)
            {
                throw new Exception(string.Join("<br>", errorMessages));
            }

            var workflowOutput = await _cancelPending.InvokeAsync(new WorkflowInput { { "Exams", exams } });
            exams.ForEach(async e =>
            {
                if (e.ExamQueuing != null && e.ExamQueuing.IsPending)
                {
                    e.ExamQueuing.Status = ExamQueuingStatus.Wait;
                    e.ExamQueuing.IsPending = false;

                    await _examEventService.AddExamEventAsync(e, "取消挂起");
                }
            });

            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> RefundAsync(WorkflowInput input, string nextApi = null)
    {
        try
        {
            var examIds = JsonConvert.DeserializeObject<IList<Guid>>(input.GetValueOrDefault("examIds").ToString() ?? "[]");
            if (examIds.Count == 0)
            {
                return new WorkflowOutput
                {
                    Success = false,
                    Error = "没有找到需要退费的检查"
                };
            }
            var exams = await _examRepository.GetListAsync(e => examIds.Contains(e.Oid));
            foreach (var exam in exams)
            {
                if (!await _examPermissionService.IsValidAsync(exam))
                {
                    throw new Exception($"检查【{exam.AccessionNumber}】不属于本科室");
                }
            }
            var userName = input.GetValueOrDefault("userName")?.ToString();
            var password = input.GetValueOrDefault("password")?.ToString();
            if (string.IsNullOrWhiteSpace(userName))
            {
                var workflowOutput = await _accountVerifyService.GetVerifyViewAsync();
                if (!string.IsNullOrWhiteSpace(nextApi))
                {
                    workflowOutput.NextApi = nextApi;
                }
                return workflowOutput;
            }
            else
            {
                var workflowOutput = await _accountVerifyService.VerifyAsync(userName, password, "登记_退费", exams[0]);
                if (workflowOutput.Success)
                {
                    workflowOutput = await _refund.InvokeAsync(new WorkflowInput { { "Exams", exams } });
                }
                return workflowOutput;
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> ArrivedAsync(WorkflowInput input, string nextApi = null)
    {
        try
        {
            var examIds = JsonConvert.DeserializeObject<IList<Guid>>(input.GetValueOrDefault("examIds").ToString() ?? "[]");
            if (examIds.Count == 0)
            {
                return new WorkflowOutput
                {
                    Success = false,
                    Error = "没有找到需要到诊的检查"
                };
            }
            //到诊  创建一个等候队列
            var exams = await _examRepository.GetListAsync(e => examIds.Contains(e.Oid));
            var department = await _departmentRepository.GetAsync(_currentUserOrganization.DepartmentId.Value);
            List<string> errorMessages = [];

            foreach (var exam in exams)
            {
                var errorMessage = VerifyArrived(exam, department);
                if (errorMessage != null)
                {
                    errorMessages.Add(errorMessage);
                }
            }
            if (errorMessages.Count > 0)
            {
                throw new Exception(string.Join("<br>", errorMessages));
            }
            if (exams.Count > 1)
            {
                foreach (var exam in exams)
                {
                    if (exam.ExamStatus == ExamStatus.Appointment)
                    {
                        exam.ExamQueuing = await _examQueueService.CreateExamQueuingAsync(exam, true);
                        exam.ExamStatus = ExamStatus.Triage;
                        await _examNumberService.SetQueueNumberAsync(exam.ExamQueuing);
                        await _examNumberService.SetNumberAsync(exam);
                        await _examEventService.AddExamEventAsync(exam, "患者到诊");
                    }
                }
            }
            else
            {
                var exam = exams[0];
                var initSelectedDeviceId = input.GetValueOrDefault("initSelected")?.ToString();
                if (string.IsNullOrWhiteSpace(initSelectedDeviceId))
                {
                    var patientName = exam.Patient.Name;
                    var appointmentNumber = exam.ExamAppointment?.AppointmentNumber;
                    var appointmentTime = exam.ExamAppointment?.StartTime;
                    var appointmentTimeText = appointmentTime?.ToString();
                    if (appointmentTime.HasValue)
                    {
                        var now = Clock.Now.Date;
                        appointmentTimeText = appointmentTime.Value.ToString("yyyy-MM-dd HH:mm");
                        if (now > appointmentTime.Value)
                        {
                            appointmentTimeText = $"{appointmentTimeText} (预约过期)";
                        }
                        else if (now.AddDays(1) <= appointmentTime.Value)
                        {
                            appointmentTimeText = $"{appointmentTimeText} (未到时间)";
                        }
                    }

                    // 展示视图
                    // 设置默认值
                    return new WorkflowOutput
                    {
                        Success = true,
                        ViewTitle = "选择诊室",
                        View = await Extensions.GetResourceStringAsync("Resources.Register.arrive-view.json"),
                        Data = new
                        {
                            InitSelected = exam.ExamDevice?.Oid,
                            SelectedDevice = exam.ExamDevice?.Oid,
                            patientName,
                            appointmentNumber,
                            appointmentTimeText,
                        },
                        Content = new
                        {
                            DeviceTypeId = exam.DeviceType?.Oid,
                            ExamId = exam.Oid
                        },
                        ViewWidth = "850px",
                        NextApi = !string.IsNullOrWhiteSpace(nextApi) ? nextApi : null
                    };
                }
                else
                {
                    var deviceId = input.GetValueOrDefault("selectedDevice")?.ToString();
                    if (!string.IsNullOrWhiteSpace(deviceId))
                    {
                        // 设置诊室和设备
                        var device = await _deviceRepository.GetAsync(Guid.Parse(deviceId));
                        exam.ExamDevice = device;
                        exam.ExamQueuing = await _examQueueService.CreateExamQueuingAsync(exam, true);
                        exam.ExamStatus = ExamStatus.Triage;
                        await _examNumberService.SetQueueNumberAsync(exam.ExamQueuing);
                        await _examNumberService.SetNumberAsync(exam);
                        await _examEventService.AddExamEventAsync(exam, "患者到诊");
                    }
                }
            }
            var workflowOutput = await _setArrived.InvokeAsync(new WorkflowInput { { "Exams", exams } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            workflowOutput = await _candidate.InvokeAsync(new WorkflowInput { { "Exams", exams } });
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    private string VerifyArrived(Exam exam, Department department)
    {
        if (exam.ExamStatus == ExamStatus.Create)
        {
            return $"当前检查【{exam.Patient.Name}({exam.ExamAppointment?.AppointmentNumber})】未提交";
        }
        else if (exam.ExamStatus != ExamStatus.Appointment)
        {
            return $"当前检查【{exam.Patient.Name}({exam.ExamAppointment?.AppointmentNumber})】已到诊";
        }
        //不是当前科室
        if (exam.Department != department)
        {
            return $"当前检查【{exam.Patient.Name}({exam.ExamAppointment?.AppointmentNumber})】不属于本科室";
        }
        if (exam.ExamQueuing != null)
        {
            return $"当前检查【{exam.Patient.Name}({exam.ExamAppointment?.AppointmentNumber})】已在等候队列";
        }
        if (exam.Report != null)
        {
            return $"当前检查【{exam.Patient.Name}({exam.ExamAppointment?.AppointmentNumber})】已存在报告";
        }
        //时间
        if (exam.ExamAppointment == null)
        {
            return $"当前检查【{exam.Patient.Name}({exam.ExamAppointment?.AppointmentNumber})】不存在预约计划";
        }
        return null;
    }

    public async Task<WorkflowOutput> TopAsync(Guid examId)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            await _examPermissionService.ValidateAsync(exam);
            var department = await _departmentRepository.GetAsync(_currentUserOrganization.DepartmentId.Value);
            var errorMessage = VerifyQueuing(exam, department);
            if (errorMessage != null)
            {
                throw new Exception(errorMessage);
            }
            if (exam.ExamQueuing != null && exam.ExamQueuing.IsPending)
            {
                exam.ExamQueuing.Status = ExamQueuingStatus.Wait;
                exam.ExamQueuing.IsPending = false;
            }
            var workflowOutput = await _setTop.InvokeAsync(new WorkflowInput { { "Exam", exam } });
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> BottomAsync(Guid examId)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            await _examPermissionService.ValidateAsync(exam);
            var department = await _departmentRepository.GetAsync(_currentUserOrganization.DepartmentId.Value);
            var errorMessage = VerifyQueuing(exam, department);
            if (errorMessage != null)
            {
                throw new Exception(errorMessage);
            }
            if (exam.ExamQueuing != null && exam.ExamQueuing.IsPending)
            {
                exam.ExamQueuing.Status = ExamQueuingStatus.Wait;
                exam.ExamQueuing.IsPending = false;
            }
            var workflowOutput = await _setBottom.InvokeAsync(new WorkflowInput { { "Exam", exam } });
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> PreviousAsync(Guid examId)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            await _examPermissionService.ValidateAsync(exam);
            var workflowOutput = await _setPrevious.InvokeAsync(new WorkflowInput { { "Exam", exam } });
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> NextAsync(Guid examId)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            await _examPermissionService.ValidateAsync(exam);
            var workflowOutput = await _setNext.InvokeAsync(new WorkflowInput { { "Exam", exam } });
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> EmergencyRegisterAsync()
    {
        try
        {
            var input = new WorkflowInput();
            var workflowOutput = await _getEmergencyRegistView.InvokeAsync(input);
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public Task<WorkflowOutput> TransferRoomAsync(IList<Guid> examIds, Guid roomId)
    {
        throw new NotImplementedException();
    }
}
